<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2024/3/20
 * Time: 11:46
 */

namespace app\queue\generatedplanpartimage;

use app\common\lib\Common;
use app\common\lib\Constant;
use app\common\lib\DetectFaceAdvance;
use app\common\lib\Guzzle;
use app\common\lib\MoyinTts;
use app\common\lib\RedisQueue;
use app\common\lib\TencentTts;
use app\exception\IndexException;
use app\model\consume\ConsumePointLogModel;
use app\model\image\ImageModelModel;
use app\model\novel\NovelChapterModel;
use app\model\novel\NovelChapterPartModel;
use app\model\plan\PromotionPlanModel;
use app\model\plan\PromotionPlanPartImageModel;
use app\model\plan\PromotionPlanWorkModel;
use app\model\plan\PromotionPlanWorkPartModel;
use app\model\queue\AiImageRequestQueueModel;
use app\model\redis\RedisQueueModel;
use app\model\tencent\TimbreModel;
use app\model\user\UserNovelChapterPartModel;
use app\model\user\UserPointFlowModel;
use app\model\user\UserPromotionPlanModel;
use app\model\novel\NovelPlanRoleModel;
use support\Cache;
use support\Db;
use Webman\RedisQueue\Consumer;
use app\common\lib\TencentCos;

class AsyncGeneratedPlanPartImage  implements Consumer
{
    // 要消费的队列名
    public $queue = 'asyncGeneratedPlanPartImage';

    // 连接名，对应 plugin/webman/redis-queue/redis.php 里的连接`
    public $connection = 'default';

    protected $resultData = [];

    // 消费
    public function consume($data)
    {
        Common::initQueueConfig();

        $queue = RedisQueueModel::getInstance()->find($data['queueid']);
        $queue->exec_time = date('Y-m-d H:i:s');
        $queue->save();

        try{
            // 无需反序列化
            $result = $this->handle($data);

            RedisQueue::getInstance()->saveQueue($this->queue,$data,$result);
        }catch (IndexException $e){
            RedisQueue::getInstance()->saveQueue($this->queue,$data,['error'=>$e->getMessage()]);
            Common::queueExecptionReport($queue,$data,$e);
        }catch (\Throwable $e){
            RedisQueue::getInstance()->saveQueue($this->queue,$data,['error'=>$e->getMessage()]);
            Common::queueExecptionReport($queue,$data,$e);
        }
    }

    protected function handle($data)
    {
        //todo  生成创作内容片段-ai漫画
        $this->generatedDescAndAIImage($data);

        return ['success'];
    }

    protected function generatedDescAndAIImage($data)
    {
        $requestIdMap = [];
        $planData = PromotionPlanPartImageModel::getInstance()->getWhere(['planid'=>$data['planid'],'status'=>0,['created_at','>=',$data['created_at']]])->get();
        foreach ($planData as $plan){
            $aiImageCommands = json_decode($plan['ai_image_command'], true);
            if($aiImageCommands==false){
                continue;
            }
            $modelVal = $aiImageCommands['override_settings']['sd_model_checkpoint']??'';
            if($modelVal==false){
                continue;
            }

            $imageNums = 1;
            $aiImageCommand = $plan['ai_image_command'];

            $width = 1024;
            $height = 1024;

            $prompt = $plan['prompt'];

            $source = 'cron_plan_part_image_save_'.$plan['id'];
            $options = [
                'width' => $width, 'height' => $height, 'batch_size' => $imageNums,
                'seed'  => ($plan['ai_image_command_seed'] ?: -1), 'command_template_id' => $plan['ai_image_command_id'] ?? 0
            ];
            if(!empty($plan['more_people_prompt'])){
                $options['more_people_prompt'] = $plan['more_people_prompt'];
            }
            if(!empty($plan['refer_image'])){
                $aiImageCommands['init_images'] = [$plan['refer_image']];
                $aiImageCommand = json_encode($aiImageCommands,256);
            }
            $requestId = Common::generatedAIImageByTemplate($aiImageCommand,$prompt,$modelVal,$options,$source,$data['requestid']??'');
            $requestIdMap[$requestId] = $plan;
        }

        foreach ($requestIdMap as $requestId=>$plan){
            while (true){
                $aiImages = Common::getAiImageResult($requestId);
                if(!empty($aiImages) && is_array($aiImages)){
                    //获取人脸识别数据
                    $aiImageFaceArrs = [];
                    foreach($aiImages as $k=>$image){
                        $aiImageFaceArr = [];
                        $aiImageFaceArr['link'] = $image;
                        $aiImageFaceArr['faceRectangles'] = [];
                        try{
                            $res = DetectFaceAdvance::getInstance()->getFaceBody($image);
                            if(!empty($res['Data']['FaceRectangles'])){
                                $aiImageFaceArr['faceRectangles'] = $res['Data']['FaceRectangles'];
                            }
                        }catch (\Throwable $e){}

                        $aiImageFaceArrs[] = $aiImageFaceArr;

                        //这里加上休眠是因为QPS 5/s
                        //只要一个图数据即可
                        break;
                    }

                    $update = [];
                    $update['status'] = 1;
                    $update['ai_image'] = $aiImages[0];
                    $update['ai_image_face_arr'] = json_encode($aiImageFaceArrs,256);
                    PromotionPlanPartImageModel::getInstance()->getWhere(['id'=>$plan['id']])->update($update);
                    break;
                }
                sleep(3);

                $first = (new AiImageRequestQueueModel())->getWhere(['requestid'=>$requestId])->first();
                if($first && !empty($first['start_time']) && (time()-strtotime($first['start_time']))>300){
                    throw new IndexException(4020,'生成超时');
                }elseif ($first==false){
                    throw new IndexException(4020,'加入队列失败');
                }
            }
        }
        return true;
    }

    // 消费失败回调
    /*
    $package = [
        'id' => 1357277951, // 消息ID
        'time' => 1709170510, // 消息时间
        'delay' => 0, // 延迟时间
        'attempts' => 2, // 消费次数
        'queue' => 'send-mail', // 队列名
        'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容
        'max_attempts' => 5, // 最大重试次数
        'error' => '错误信息' // 错误信息
    ]
    */
    public function onConsumeFailure(\Throwable $e, $package)
    {
//        echo "consume failure\n";
//        echo $e->getMessage() . "\n";
//        // 无需反序列化
//        var_export($package);

        RedisQueue::getInstance()->saveQueue($this->queue,$package['data'],['error'=>$e->getMessage()]);
    }

}